package com.zhhl.redis;

import com.jld.base.common.bean.business.RedisBean;
import com.jld.common.exception.JLDBusinessException;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

@Service("redisManageService")
public class RedisManageService extends RedisGeneratorDao<String, RedisBean>
{
  public boolean add(final RedisBean bean)
    throws JLDBusinessException
  {
    boolean result = ((Boolean)this.redisTemplate.execute(new RedisCallback() {
      public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
        byte[] key = bean.getByteKey();
        byte[] value = RedisManageService.this.serialize(bean.getValue());
        return connection.setNX(key, value);
      }
    })).booleanValue();

    return result;
  }

  public boolean add(final List<RedisBean> list)
    throws JLDBusinessException
  {
    Assert.notEmpty(list);
    boolean result = ((Boolean)this.redisTemplate.execute(new RedisCallback() {
      public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
        for (RedisBean bean : list) {
          byte[] key = bean.getByteKey();
          byte[] value = RedisManageService.this.serialize(bean.getValue());
          connection.setNX(key, value);
        }
        return Boolean.valueOf(true);
      }
    }
    , false, true)).booleanValue();

    return result;
  }

  public void delete(final String key)
  {
    this.redisTemplate.execute(new RedisCallback() {
      public Object doInRedis(RedisConnection connection) throws DataAccessException {
        return connection.del(new byte[][] { key.getBytes() });
      }
    }
    , false, true);
  }

  public void delete(List<String> keys)
  {
    final byte[][] rawKeys = new byte[keys.size()][];
    int i = 0;
    for (String key : keys) {
      rawKeys[(i++)] = key.getBytes();
    }
    this.redisTemplate.execute(new RedisCallback() {
      public Object doInRedis(RedisConnection connection) throws DataAccessException {
        return connection.del(rawKeys);
      }
    }
    , false, true);
  }

  public boolean update(final RedisBean bean)
  {
    if (get(bean.getKey()) == null) {
      throw new NullPointerException("数据行不存在, key = " + bean.getKey());
    }
    boolean result = ((Boolean)this.redisTemplate.execute(new RedisCallback() {
      public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
        byte[] key = bean.getByteKey();
        byte[] name = RedisManageService.this.serialize(bean.getValue());
        connection.set(key, name);
        return Boolean.valueOf(true);
      }
    })).booleanValue();

    return result;
  }

  public RedisBean get(final String keyId)
  {
    RedisBean result = (RedisBean)this.redisTemplate.execute(new RedisCallback() {
      public RedisBean doInRedis(RedisConnection connection) throws DataAccessException {
        byte[] key = keyId.getBytes();
        byte[] val = connection.get(key);
        if (val == null) {
          return null;
        }
        Object value = RedisManageService.this.unserialize(val);
        return new RedisBean(keyId, value);
      }
    });
    return result;
  }
  
  /**
   * 新增ZSET
 * @param bean
 * @return
 * @throws JLDBusinessException
 */
  public boolean zadd(final RedisBean bean ,Double score)throws JLDBusinessException{
	  boolean result = ((Boolean)this.redisTemplate.execute(new RedisCallback() {
	      public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
	        byte[] key = bean.getByteKey();
	        byte[] value = RedisManageService.this.serialize(bean.getValue());
	        return connection.zAdd(key, score, value);
	        
	      }
	    })).booleanValue();
	    return result;
  }
  
  /**输出zset中指定范围内的的所有元素，按照score从zrevrange从大到小,zrange是小到大的顺序 
 * @param bean
 * @param begin
 * @param end
 * @return
 * @throws JLDBusinessException
 */
public List<RedisBean> zRevRange(final String key,final Long begin,final Long end)throws JLDBusinessException{
	  
	  List<RedisBean> result = (List<RedisBean>)this.redisTemplate.execute(new RedisCallback() {
	      public List<RedisBean> doInRedis(RedisConnection connection) throws DataAccessException {
	        Set<byte[]> setbyte =  connection.zRevRange(key.getBytes(), begin, end);
	        if (setbyte == null) {
	          return null;
	        }
	        List<RedisBean> listrb = new ArrayList<RedisBean>();
	        for(byte[] bb:setbyte){
	        	Object value = RedisManageService.this.unserialize(bb);
	        	RedisBean aa = new RedisBean(key.toString(),value);
	        	listrb.add(aa);
	        }
	        return listrb;
	      }
	    });
	    return result;
	    
  }
  
  /**zremrangebyscore 删除score在指定范围内的元素。例如：zremrangebyscore zset 1 2
 * @param key
 * @param min
 * @param max
 * @return
 */
public Long zremrangebyscore(final String key,final Double min,final Double max){
	  Long result = (Long)this.redisTemplate.execute(new RedisCallback() {
      public Object doInRedis(RedisConnection connection) throws DataAccessException {
    	  return connection.zRemRangeByScore(key.getBytes(), min, max);
      }
    });
    return result;
  }
  
  /**返回集合中score在给定区间的数量。zcount zset 2 3
 * @param key
 * @param min
 * @param max
 * @return
 */
public Long zcount(final String key,final Double min,final Double max){
	  Long result = (Long)this.redisTemplate.execute(new RedisCallback() {
      public Object doInRedis(RedisConnection connection) throws DataAccessException {
    	  return connection.zCount(key.getBytes(), min, max);
      }
    });
    return result;
  }
  
  
}